package com.example.mvvm.base;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

import com.example.mvvm.R;
import com.example.mvvm.base.action.ActivityAction;
import com.example.mvvm.base.action.BundleAction;
import com.example.mvvm.base.action.ClickAction;
import com.example.mvvm.base.action.HandlerAction;
import com.example.mvvm.base.action.ResourcesAction;
import com.example.mvvm.base.action.TitleBarAction;
import com.example.mvvm.base.cache.CacheUtils;
import com.example.mvvm.base.data.DataBindingConfig;
import com.example.mvvm.base.data.DialogTipBean;
import com.example.mvvm.base.data.IntentData;
import com.example.mvvm.base.vm.BaseViewModel;
import com.example.mvvm.base.vm.ParameterField;
import com.example.mvvm.until.ActivityManager;
import com.example.mvvm.until.Tips;

import java.util.Map;
import java.util.Random;

import sion.my.netmanger2.NetworkManager;
import sion.my.netmanger2.annotations.NetType;
import sion.my.netmanger2.enums.NetMode;

/**
 * @ClassName PlugBaseActivity
 * @Description
 * @Author dogeWen
 * @Date 2021/4/6 14:45
 */
public abstract class BaseActivity<B extends ViewDataBinding> extends FragmentActivity implements
        ActivityAction,
        BundleAction,
        ClickAction,
        TitleBarAction,
        HandlerAction,
        ResourcesAction {
    public String TAG = this.getClass().getSimpleName();
    Handler HANDLER = new Handler(Looper.getMainLooper(),getHandleCallBack());
    @Override
    public Handler getHandler() {
        return HANDLER;
    }
    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return super.getLifecycle();
    }

    protected abstract DataBindingConfig getDataBindingConfig();

    private ViewModelProvider mActivityProvider;
    private B binding;
    private ViewModelProvider mApplicationProvider;

    protected abstract void initViewModel();

    public boolean isAddActivityStock() {
        return true;
    }

    @Override
    protected void onDestroy() {
        if (isAddActivityStock()) {
            ActivityManager.getInstance().removeActivity(this.getClass());
        }
        removeCallbacks();
        super.onDestroy();
    }

    protected void initViewObservable() {
        BaseViewModel viewModel = getDataBindingConfig().getStateViewModel();
        if (viewModel != null) {
            viewModel.getUi().getDialogShowEvent().observe(this, show -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        if (show) {
                            DialogTipBean value = viewModel.getUi().getDialogTipEvent().getValue();
                            showDialog(value.tip,value.touch);
                        } else {
                            hideDialog();
                        }
                    }
                });
            });
            viewModel.getUi().getShortTipEvent().observe(this, info -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        Tips.showStatus(getContext(), Toast.LENGTH_SHORT, info.status, info.msg);
                    }
                });
            });
            viewModel.getUi().getLongToastEvent().observe(this, info -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        showLongToast(info);
                    }
                });
            });

            viewModel.getUi().getShortToastEvent().observe(this, info -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        showShortToast(info);
                    }
                });
            });

            viewModel.getContext().getStartContainerActivityEvent().observe(this, map -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        startContainerActivity(map);
                    }
                });

            });

            viewModel.getContext().getStartActivityEvent().observe(this, map -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        startActivityEvent(map);
                    }
                });
            });

            viewModel.getContext().getFinishEvent().observe(this, aVoid -> {
                HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        finish();
                    }
                });

            });
        }
    }

    public B getBinding() {
        return binding;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        Log.i(TAG, "onCreate");
        if (isAddActivityStock()) {
            ActivityManager.getInstance().addActivity(this.getClass(), this);
        }
        super.onCreate(savedInstanceState);
        initParam(getIntent());
        initViewModel();
        DataBindingConfig dataBindingConfig = getDataBindingConfig();
        binding = DataBindingUtil.setContentView(this, dataBindingConfig.getLayout());
        binding.setLifecycleOwner(this);
        if (dataBindingConfig.getVmVariableId() != 0) {
            BaseViewModel stateViewModel = dataBindingConfig.getStateViewModel();
            getLifecycle().addObserver(stateViewModel);
            binding.setVariable(dataBindingConfig.getVmVariableId(), stateViewModel);
        }
        SparseArray bindingParams = dataBindingConfig.getBindingParams();
        for (int i = 0, length = bindingParams.size(); i < length; i++) {
            binding.setVariable(bindingParams.keyAt(i), bindingParams.valueAt(i));
        }
        initViewObservable();

    }

    public abstract void showDialog(String info);

    public abstract void showDialog(String info,boolean touch);

    public abstract void hideDialog();

    protected void showLongToast(String text) {
        Tips.show(this, text, Toast.LENGTH_LONG);
    }

    protected void showShortToast(String text) {
        Tips.show(this, text);
    }

    protected void showLongToast(int stringRes) {
        Tips.show(this, getString(stringRes), Toast.LENGTH_LONG);
    }

    protected void showShortToast(int stringRes) {
        Tips.show(this, getString(stringRes));
    }

    protected void startContainerActivity(Map<String, Object> params) {
        if (params != null) {
            String canonicalName = (String) params.get(ParameterField.CANONICAL_NAME);
            Bundle bundle = (Bundle) params.get(ParameterField.BUNDLE);
            startContainerActivity(canonicalName, bundle);
        }
    }

    /**
     * 跳转容器页面
     *
     * @param canonicalName 规范名 : Fragment.class.getCanonicalName()
     * @param bundle        跳转所携带的信息
     */
    public void startContainerActivity(String canonicalName, Bundle bundle) {
        Intent intent = new Intent(this, ContainerActivity.class);
        intent.putExtra(ContainerActivity.FRAGMENT, canonicalName);
        if (bundle != null) {
            intent.putExtra(ContainerActivity.BUNDLE, bundle);
            boolean login = bundle.containsKey("LOGIN");
            if (login) {
                boolean isLogin = CacheUtils.getLogin();
                if (isLogin && getLoginActivity() != null) {
                    startActivity(getLoginActivity());
                    return;
                }
            }
        }
        startActivity(intent);
    }

    public abstract Class getLoginActivity();

    @Override
    public void onClick(View v) {
    }

    /**
     * 隐藏软键盘
     */
    private void hideSoftKeyboard() {
        // 隐藏软键盘，避免软键盘引发的内存泄露
        View view = getCurrentFocus();
        if (view != null) {
            InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            if (manager != null && manager.isActive(view)) {
                manager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
    }

    @Override
    public void finish() {
        hideSoftKeyboard();
        super.finish();
    }

    @Override
    public void onBackPressed() {
        hideSoftKeyboard();
        super.onBackPressed();
    }

    protected void startActivityEvent(Map<String, Object> params) {
        if (params != null) {
            Class<?> clz = (Class<?>) params.get(ParameterField.CLASS);
            Bundle bundle = (Bundle) params.get(ParameterField.BUNDLE);
            Boolean finish = (Boolean) params.get(ParameterField.FINISH);
            startActivity(clz, bundle, finish);
        }
    }

    /**
     * 跳转页面
     *
     * @param clz    所跳转的目的Activity类
     * @param bundle 跳转所携带的信息
     */
    public void startActivity(Class<?> clz, Bundle bundle, boolean finish) {
        Intent intent = new Intent(this, clz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        if (finish) {
            startActivityFinish(intent);
        } else {
            startActivity(intent);
            overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
        }
    }

    /**
     * startActivity 方法优化
     */

    public void startActivity(Class<? extends Activity> cls) {
        startActivity(new Intent(this, cls));
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
    }

    public void startActivityFinish(Class<? extends Activity> cls) {
        startActivityFinish(new IntentData(this, cls));
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
    }

    public void startActivityFinish(Intent intent) {
        startActivity(intent);
        finish();
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
    }

    public void startActivityFinish(IntentData intent) {
        startActivity(intent);
        finish();
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
    }

    public ActivityCallback mActivityCallback;
    private int mActivityRequestCode;

    /**
     * Activity 回调接口
     */
    public interface ActivityCallback {

        /**
         * 结果回调
         *
         * @param resultCode 结果码
         * @param data       数据
         */
        void onActivityResult(int resultCode, @Nullable Intent data);
    }

    public void startActivityForResult(Class<? extends Activity> cls, ActivityCallback callback) {
        startActivityForResult(new Intent(this, cls), null, callback);
    }

    public void startActivityForResult(Intent intent, ActivityCallback callback) {
        startActivityForResult(intent, null, callback);
    }

    public void startActivityForResult(Intent intent, @Nullable Bundle options, ActivityCallback callback) {
        // 回调还没有结束，所以不能再次调用此方法，这个方法只适合一对一回调，其他需求请使用原生的方法实现
        if (mActivityCallback == null) {
            mActivityCallback = callback;

            // 随机生成请求码，这个请求码在 0 - 255 之间
            mActivityRequestCode = new Random().nextInt(255);
            startActivityForResult(intent, mActivityRequestCode, options);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (mActivityCallback != null && mActivityRequestCode == requestCode) {
            mActivityCallback.onActivityResult(resultCode, data);
            mActivityCallback = null;
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    protected <T extends ViewModel> T getActivityScopeViewModel(@NonNull Class<T> modelClass) {
        if (mActivityProvider == null) {
            mActivityProvider = new ViewModelProvider(this);
        }
        return mActivityProvider.get(modelClass);
    }


    protected <T extends ViewModel> T getActivityScopeViewModel(@NonNull Class<T> modelClass, BaseActivity activity) {
        return new ViewModelProvider(activity).get(modelClass);
    }

    protected <T extends ViewModel> T getApplicationScopeViewModel(@NonNull Class<T> modelClass) {
        if (mApplicationProvider == null) {
            mApplicationProvider = new ViewModelProvider((BaseApplication) this.getApplicationContext(),
                    getAppFactory(this));
        }
        return mApplicationProvider.get(modelClass);
    }

    private ViewModelProvider.Factory getAppFactory(Activity activity) {
        Application application = checkApplication(activity);
        return ViewModelProvider.AndroidViewModelFactory.getInstance(application);
    }

    private Application checkApplication(Activity activity) {
        Application application = activity.getApplication();
        if (application == null) {
            throw new IllegalStateException("Your activity/fragment is not yet attached to "
                    + "Application. You can't request ViewModel before onCreate call.");
        }
        return application;
    }

    @Nullable
    @Override
    public Bundle getBundle() {
        return getIntent().getExtras();
    }

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    public void onLeftClick(View v) {
        finish();
    }

    public void initParam(Intent intent) {
    }

    @Override
    protected void onResume() {
        super.onResume();
        NetworkManager.getDefault().registerObserver(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        NetworkManager.getDefault().unRegisterObserver(this);
    }

    public void startActivity(Class<? extends Activity> cls, Bundle bundle) {
        Intent intent = new Intent(this, cls);
        intent.putExtras(bundle);
        startActivity(intent);
    }

    public void startActivityFinish(Class<? extends Activity> cls, Bundle bundle) {
        Intent intent = new Intent(this, cls);
        intent.putExtras(bundle);
        startActivityFinish(intent);
    }

    @NetType(nettype = NetMode.AUTO)
    public void visableNetWork(NetMode netMode) {
        if (getDataBindingConfig() != null && getDataBindingConfig().getStateViewModel() != null) {
            getDataBindingConfig().getStateViewModel().netWorkChange(netMode);
        }
        switch (netMode) {
            case NONE:
                //无网络
                break;
            case AUTO:
                //有网络
                break;
            case CMNET:
                //笔记本电脑 PDA网络
                break;
            case WIFT:
                //WIFI
                break;
            default:
                break;
        }
    }


}